/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Permissive License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Permissive License, please send an email to 
 * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Permissive License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Shell;
using System.Reflection;


namespace Nua.Hosting 
{
   
    /// <summary>
    /// A simple Python command-line should mimic the standard python.exe
    /// </summary>
    public class NuaCommandLine : CommandLine {

        private new NuaConsoleOptions Options { get { return (NuaConsoleOptions)base.Options; } }
        private new NuaEngine Engine { get { return (NuaEngine)base.Engine; } }
        
        public NuaCommandLine() {
        }

        protected override string Logo 
        {
            get 
            {
                return "Nua console";
            }
        }
       
        
        #region Initialization

        protected override void Initialize() 
        {
            InitializePath();
            InitializeModules();
            ImportSite();
        }
        
        private ScriptModule CreateMainModule() {
            ModuleOptions trueDiv = (ScriptDomainManager.Options.Division == DivisionOption.New) ? ModuleOptions.TrueDivision : ModuleOptions.None;
            ScriptModule module = Engine.CreateModule("test.exe", trueDiv | ModuleOptions.PublishModule);

            // TODO: 
            // module.Scope.SetName(Symbols.Doc, null);
            return module;
        }

        
        private void InitializePath() 
        {
            // TODO://
            Engine.AddToPath(Environment.CurrentDirectory);
        }

        private string InitializeModules() 
        {
            string version = Engine.VersionString;
            
            this.Module = CreateMainModule();
         
            //Engine.InitializeModules("prefix", executable, version);
            return version;
        }

        private void ImportSite()
        {

        }

        #endregion

        #region Interactive

        protected override int RunInteractive() {
            PrintLogo();

            int result = 1;
            try {
                RunStartup();
                result = 0;
            } 
            catch (Exception ex) 
            {
                Console.WriteLine("exception occurred", Style.Error);
            } 

            result = RunInteractiveLoop();

            return (int)result;
        }
        
        private void RunStartup() 
        {
            string startup = Environment.GetEnvironmentVariable("IRONPYTHONSTARTUP");
            if (startup != null && startup.Length > 0) {
                if (Options.HandleExceptions) {
                    try {
                        Engine.ExecuteFileContent(startup, Module);
                    } catch (Exception e) {
                       Console.WriteLine("exception occured", Style.Error);
                    } finally {
                        Engine.DumpDebugInfo();
                    }
                } else {
                    try {
                        Engine.ExecuteFileContent(startup, Module);
                    } finally {
                        Engine.DumpDebugInfo();
                    }
                }
            }
        }

        public override int? TryInteractiveAction() 
        {
            throw new NotImplementedException();

            try {
                return base.TryInteractiveAction();
            } catch (Exception se) {
                Console.WriteLine("exception occurred", Style.Error);
            }

            throw new NotImplementedException();
        }

        protected override string ReadLine(int autoIndentSize) 
        {
            throw new NotImplementedException();
        }

        protected override int GetNextAutoIndentSize(string text) 
        {
            throw new NotImplementedException();
        }

#endregion

        #region Command

        protected override int RunCommand(string command) {
            int result = 1;

            if (Options.HandleExceptions) 
            {
                try {
                    Engine.ExecuteCommand(command);
                    result = 0;
                } 
                catch (Exception pythonSystemExit) 
                {
                    Console.WriteLine("exception occured", Style.Error);
                }
            } else {
                try {
                    Engine.ExecuteCommand(command);
                    result = 0;
                } catch (Exception pythonSystemExit) {
                    Console.WriteLine("exception occured", Style.Error);
                }
            }

            return result;
        }

        #endregion

        #region File

        protected override int RunFile(string filename) {

            // TODO: must precede path initialization! (??? - test test_importpkg.py)
            //if (filename == "-") {
            //    filename = "<stdin>";
            //} else {
            //    if (!File.Exists(filename)) {
            //        Console.WriteLine(String.Format("File {0} does not exist.", filename), Style.Error);
            //        return 1;
            //    }
            //    Engine.AddToPath(Path.GetDirectoryName(Path.GetFullPath(filename)));
            //}

            int result = 1;
            if (Options.HandleExceptions) {
                try {
                    result = RunFileWorker(filename);
                } catch (Exception e) {
                    Console.Write(Engine.FormatException(e), Style.Error);
                }
            } else {
                result = RunFileWorker(filename);
            }

            return result;
        }        
        
        private int RunFileWorker(string fileName) {
            try 
            {
                // TODO: move to compiler options
                ScriptDomainManager.Options.AssemblyGenAttributes |=
                    Microsoft.Scripting.Internal.Generation.AssemblyGenAttributes.SaveAndReloadAssemblies;

                ScriptDomainManager.Options.AssemblyGenAttributes |=
                    Microsoft.Scripting.Internal.Generation.AssemblyGenAttributes.GenerateDebugAssemblies;
                
                ScriptModule engineModule = Engine.CreateOptimizedModule(fileName, "test.exe", true);

                if (Options.Introspection)
                    Module = engineModule;

                engineModule.Execute();
                return 0;

            } 
            catch (Exception ex) 
            {
                
                // disable introspection when exited:
                 Options.Introspection = false;

                return 0;
            }
        }

        #endregion
    }
}
